package com.example.springbootdemo.web;

import com.google.gson.Gson;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/toTalk/{id}")
public class TalkAction {

    // ConcurrentHashMap 线程安全的 map 集合
    // static WebSocket 服务端点是原型模式对象, 必须使用静态集合管理会话对象
    static Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(@PathParam("id") String id, Session session){
        System.out.printf("连接上线: " + id);
        //        向当前会话发送已在线人数
        sessionMap.values().forEach(s->{
            String id1 = (String) s.getUserProperties().get("id");
            Msg msg = new Msg("onlined", id1, null);
            Gson gson = new Gson();
            String message = gson.toJson(msg);
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("消息发送失败",e);
            }
        });

        sessionMap.put(id, session);
        session.getUserProperties().put("id",id);
        Msg msg = new Msg("online", id, null);
        send(msg);
    }

    @OnClose
    public void onClose(Session session){
        String id = (String) session.getUserProperties().get("id");
        System.out.printf("断链下线: " + id);
        sessionMap.remove(id);
        Msg msg = new Msg("downline", id, null);
        send(msg);
    }

    /**
     * @param message   发送的消息
     * @param session   发送者的会话
     */
    @OnMessage
    public void onMessage(String message, Session session){
        String id = (String) session.getUserProperties().get("id");
        System.out.printf("接收消息: " + id + " : " + message);
        Msg msg = new Msg("send", id, message);
        send(msg);
    }

    public void send(Msg msg){
        Gson gson = new Gson();
        String message = gson.toJson(msg);
        sessionMap.values().forEach(s->{
            RemoteEndpoint.Basic basicRemote = s.getBasicRemote();
            try {
                basicRemote.sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("消息发送失败",e);
            }
        });
    }


}

@Data
@AllArgsConstructor
class Msg {
    String type;    // 消息类型
    String id;      // 发送人
    String msg;     // 消息
}

